﻿
namespace n_UserModule
{
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

using n_GUIcoder;

//*****************************************************
//自定义组件类
public class UserModule
{
	public delegate string D_SetValue( string Mes );
	public static D_SetValue deleSetValue;
	
	public delegate int D_PortRead();
	public static D_PortRead delePortRead;
	
	//虚拟机内存
	public static byte[] BASE;
	
	public string Version;
	public string Name;
	public Image ModuleBackImage;
	
	//图片所在的文件目录, 仅用于修改模块时进行提示, 没有其他作用
	public string ImagePath;
	
	//用户名称列表(各种语言)
	public string UserName;
	//型号
	public string DeviceType;
	
	//实物照片列表
	public string ImageList;
	
	//驱动文件路径(B文件)
	public string DriverFilePath;
	
	//驱动配置信息
	public string Config;
	
	//描述文档路径
	public string MesFilePath;
	
	//扩展参数
	public string EXMes;
	
	public int X;
	public int Y;
	public int Width;
	public int Height;
	public bool isControlModule;
	public bool isClientModule;
	public bool isClientControlPad;
	public bool isClientChannel;
	public bool isVHRemoModule;
	public bool isYuanJian;
	public bool CanSwap;
	
	bool isMousePress;
	int Last_mX, Last_mY;
	
	//鼠标当前是否在组件上
	bool isMouseIn;
	
	Pen 组件高亮边框_Pen1;
	Pen 组件高亮边框_Pen2;
	Font f;
	
	//构造函数
	public UserModule( string vName, int vX, int vY )
	{
		Name = vName;
		X = vX;
		Y = vY;
		
		Version = null;
		isMousePress = false;
		isMouseIn = false;
		isControlModule = false;
		isClientModule = false;
		isClientControlPad = false;
		isClientChannel = false;
		
		UserName = null;
		DeviceType = "";
		ImageList = null;
		DriverFilePath = null;
		EXMes = null;
		
		组件高亮边框_Pen1 = new Pen( Color.Silver, 1 );
		组件高亮边框_Pen2 = new Pen( Color.Blue, 3 );
		f = new Font( "宋体", 14, FontStyle.Bold );
	}
	
	//设置背景图片
	public void SetBackImage( Image BackImage )
	{
		ModuleBackImage = BackImage;
		ChangeSize( 0 );
	}
	
	//获取组件文本描述
	public string ToText()
	{
		string r = null;
		r += "//[Version] 1,\n";
		r += "//[基本名称] " + this.Name + ",\n";
		r += "//[DeviceType] " + this.DeviceType + ",\n";
		r += "//[背景图片路径] " + ImagePath + ",\n";
		r += "//[isControlModule] " + this.isControlModule + ",\n";
		r += "//[isClientModule] " + this.isClientModule + ",\n";
		r += "//[isClientControlPad] " + this.isClientControlPad + ",\n";
		r += "//[isClientChannel] " + this.isClientChannel + ",\n";
		r += "//[isVHRemoModule] " + this.isVHRemoModule + ",\n";
		r += "//[isYuanJian] " + this.isYuanJian + ",\n";
		r += "//[CanSwap] " + this.CanSwap + ",\n";
		r += "//[Size] " + this.Width + " " + this.Height + ",\n";
		
		if( DriverFilePath != null ) {
			r += "//[DriverFilePath] " + this.DriverFilePath + ",\n";
			r += "//[UserName] " + this.UserName + ",\n";
			r += "//[ImageList] " + this.ImageList + ",\n";
		}
		if( Config != null ) {
			r += "//[Config] " + this.Config.Replace( '\n', '`' ) + ",\n";
		}
		if( MesFilePath != null ) {
			r += "//[MesFilePath] " + this.MesFilePath + ",\n";
		}
		if( EXMes != null ) {
			r += "//[EXMes] " + this.EXMes + ",\n";
		}
		return r;
	}
	
	//导出当前图像
	public Bitmap GetCurrentImage()
	{
		//Bitmap SaveImage = new Bitmap( ModuleBackImage, Width, Height );
		//return SaveImage;
		
		return new Bitmap( ModuleBackImage );
	}
	
	//显示
	public void Draw( Graphics g )
	{
		int StartX = X - Width / 2;
		int StartY = Y - Height / 2;
		g.DrawImage( ModuleBackImage, StartX, StartY, Width, Height );
		
		//if( isMouseIn ) {
			//g.DrawRectangle( 组件高亮边框_Pen2, X - Width / 2 - 4, Y - Height / 2 - 4, Width - 1 + 8, Height - 1 + 8 );
			g.DrawRectangle( 组件高亮边框_Pen1, X - Width / 2, Y - Height / 2, Width, Height );
		//}
		g.DrawString( Name + " (" + Width + "," + Height + ")", f, Brushes.Black, X - Width / 2, Y - Height / 2 - 48 );
		g.DrawString( DeviceType, f, Brushes.CornflowerBlue, X - Width / 2, Y - Height / 2 - 28 );
	}
	
	//判断鼠标是否在当前组件上
	public bool isMouseInModule( int mX, int mY )
	{
		if( mX >= X - Width / 2 && mX <= X + Width / 2 && mY >= Y - Height / 2 && mY <= Y + Height / 2 ) {
			return true;
		}
		else {
			return false;
		}
	}
	
	//鼠标按下事件
	public bool UserMouseDown( MouseEventArgs e, int mX, int mY )
	{
		if( e.Button == MouseButtons.Left ) {
			
			if( isMouseInModule( mX, mY ) ) {
				isMousePress = true;
				Last_mX = mX;
				Last_mY = mY;
				return true;
			}
		}
		if( e.Button == MouseButtons.Right ) {
			//...
		}
		return false;
	}
	
	//鼠标松开事件
	public void UserMouseUp( MouseEventArgs e, int mX, int mY )
	{
		//组件鼠标松开事件
		isMousePress = false;
	}
	
	//鼠标移动事件
	public void UserMouseMove( MouseEventArgs e, int mX, int mY )
	{
		//组件鼠标移动事件
		isMouseIn = isMouseInModule( mX, mY );
		if( isMousePress ) {
			//X += mX - Last_mX;
			//Y += mY - Last_mY;
			
			Last_mX = mX;
			Last_mY = mY;
		}
	}
	
	//调整尺寸
	public void ChangeSize( int wioff )
	{
		Width = ModuleBackImage.Width + wioff;
		Height = (int)( ModuleBackImage.Height * (double)Width / ModuleBackImage.Width );
	}
	
	//调整尺寸
	public void ChangeSize( float wioff )
	{
		Width = (int)(ModuleBackImage.Width * wioff);
		Height = (int)( ModuleBackImage.Height * wioff );
	}
}
//*****************************************************
//端口列表类
public class UserPortList
{
	public UserPort[] PortList;
	
	public delegate void D_PortSelChanged();
	public static D_PortSelChanged PortSelChanged;
	
	public static UserPort temp;
	
	public static UserPort MouseOnPort;
	
	static UserPort t_SelectedPort;
	public static UserPort SelectedPort {
		get {
			return t_SelectedPort;
		}
		set {
			t_SelectedPort = value;
			if( PortSelChanged != null ) {
				PortSelChanged();
			}
		}
	}
	
	const int MaxPortListLength = 310;
	
	//构造函数
	public UserPortList()
	{
		PortList = new UserPort[ MaxPortListLength ];
	}
	
	//清空端口列表
	public void ClearPortList()
	{
		PortList = new UserPort[ MaxPortListLength ];
	}
	
	//添加端口,如果添加成功返回 null, 否则返回错误描述
	public string AddPort( UserPort u, bool CheckName )
	{
		if( CheckName ) {
			for( int i = 0; i < PortList.Length; ++i ) {
				if( PortList[ i ] == null ) {
					continue;
				}
				if( PortList[ i ].Name == u.Name ) {
					//return "已经有同名的端口: " + u.Name;
					MessageBox.Show( "注意: 已经有了同名端口, 请您自行确保正确性" );
					break;
				}
			}
		}
		for( int i = 0; i < PortList.Length; ++i ) {
			if( PortList[ i ] == null ) {
				PortList[ i ] = u;
				u.owner = this;
				return null;
			}
		}
		return "端口列表已满";
	}
	
	//删除一个端口
	public void Delete( UserPort up )
	{
		for( int i = 0; i < PortList.Length; ++i ) {
			if( PortList[ i ] == null ) {
				continue;
			}
			if( PortList[ i ] == up ) {
				PortList[ i ] = null;
				return;
			}
		}
	}
	
	//转换为文本描述
	public string ToText( int moduleX, int moduleY, bool isWire )
	{
		string r = "";
		
		for( int i = 0; i < PortList.Length; ++i ) {
			if( PortList[ i ] == null ) {
				continue;
			}
			if( isWire ) {
				
				if( PortList[ i ].SubPortConfig == null || PortList[ i ].SubPortConfig == "" ) {
					if( UserModule.deleSetValue != null ) {
						string Message = "//[总线] " + PortList[ i ].FuncType + " " + PortList[ i ].FuncName.Trim( ',' ) + " " +
							PortList[ i ].Name + " " + PortList[ i ].DirType + " " +
							( PortList[ i ].X - moduleX ) + " " +
							( PortList[ i ].Y - moduleY ) + " " +
							PortList[ i ].Style + " " +
							PortList[ i ].SubPortConfig + ",\n";
						PortList[ i ].SubPortConfig = UserModule.deleSetValue( Message );
					}
				}
				if( PortList[ i ].Style == null || PortList[ i ].Style == "" ) {
					PortList[ i ].Style = "IO6";
				}
				
				r += "//[总线] " + PortList[ i ].FuncType + " " + PortList[ i ].FuncName.Trim( ',' ) + " " +
					PortList[ i ].Name + " " + PortList[ i ].DirType + " " +
					( PortList[ i ].X - moduleX ) + " " +
					( PortList[ i ].Y - moduleY ) + " " +
					PortList[ i ].Style + " " +
					PortList[ i ].SubPortConfig + ",\n";
			}
			else {
				r += "//[端口] " + PortList[ i ].FuncType + " " + PortList[ i ].FuncName.Trim( ',' ) + " " +
					PortList[ i ].Name + " " + PortList[ i ].DirType + " " +
					( PortList[ i ].X - moduleX ) + " " + ( PortList[ i ].Y - moduleY ) + " " + PortList[ i ].ExtValue + ",\n";
			}
		}
		return r;
	}
	
	//显示
	public void Draw( Graphics g, bool isWireNet )
	{
		int MouseOnPortIndex = 0;
		
		//逐个绘制端口
		for( int i = 0; i < PortList.Length; ++i ) {
			if( PortList[ i ] == null ) {
				continue;
			}
			if( PortList[ i ].isMouseIn ) {
				MouseOnPort = PortList[ i ];
				MouseOnPortIndex = i;
				continue;
			}
			PortList[ i ].Draw( g, i, isWireNet );
		}
		//绘制高亮端口
		if( MouseOnPort != null ) {
			MouseOnPort.Draw( g, MouseOnPortIndex, isWireNet );
		}
	}
	
	//鼠标按下事件
	public bool UserMouseDown( MouseEventArgs e, int mX, int mY )
	{
		//分发端口鼠标按下事件
		bool isPortDown = false;
		for( int i = 0; i < PortList.Length; ++i ) {
			if( PortList[ i ] == null ) {
				continue;
			}
			if( PortList[ i ].UserMouseDown( e, mX, mY ) ) {
				isPortDown = true;
				temp = PortList[ i ];
				break;
			}
		}
		return isPortDown;
	}
	
	//鼠标松开事件
	public void UserMouseUp( MouseEventArgs e, int mX, int mY )
	{
		//分发端口鼠标松开事件
		for( int i = 0; i < PortList.Length; ++i ) {
			if( PortList[ i ] == null ) {
				continue;
			}
			PortList[ i ].UserMouseUp( e, mX, mY );	
		}
	}
	
	//鼠标移动事件
	public void UserMouseMove( MouseEventArgs e, int mX, int mY )
	{
		MouseOnPort = null;
		
		//分发端口鼠标移动事件
		for( int i = 0; i < PortList.Length; ++i ) {
			if( PortList[ i ] == null ) {
				continue;
			}
			PortList[ i ].UserMouseMove( e, mX, mY );
			
			if( PortList[ i ].isMouseIn ) {
				MouseOnPort = PortList[ i ];
			}
		}
	}
}
//*****************************************************
//端口类
public class UserPort
{
	public UserPortList owner;
	
	public string Name;
	public string FuncType;
	public string FuncName;
	public string Style;
	public string SubPortConfig;
	public E_DirType DirType;
	public string ExtValue;
	
	public float X, Y;
	
	public bool isNew;
	
	public bool isMouseIn;
	
	public bool isMousePress;
	
	Pen DirForePen;
	Pen DirBackPen;
	Pen bHighLightPortPen;
	Pen rHighLightPortPen;
	Font f;
	
	const int PortR = 3;
	const int Port2R = PortR * 2;
	
	//注意 Per 应为奇数
	//在组件设计器中也是默认为3
	public const int Per254 = 10;
	public const int Per200 = 8;
	public static int Per = Per254;
	
	public static float ox;
	public static float oy;
	
	//初始化
	public static void Init()
	{
		ox = 0;
		oy = 0;
	}
	
	//构造函数
	public UserPort( string vName, string vFuncType, string vFuncName, string vStyle, string vSubPortConfig, E_DirType vDirType, string vExtValue )
	{
		Name = vName;
		FuncType = vFuncType;
		FuncName = vFuncName;
		DirType = vDirType;
		Style = vStyle;
		SubPortConfig = vSubPortConfig;
		ExtValue = vExtValue;
		
		isMousePress = false;
		isNew = false;
		
		DirForePen = new Pen( Color.White, 1 );
		DirBackPen = new Pen( Color.FromArgb(255, 128, 0), 3 );
		DirBackPen.StartCap = LineCap.Round;
		DirBackPen.EndCap = LineCap.Round;
		bHighLightPortPen = new Pen( Color.Blue, 2 );
		rHighLightPortPen = new Pen( Color.Red, 2 );
		f = new Font( "Courier New", 12 );
	}
	
	//绘制
	public void Draw( Graphics g, int Index, bool isWireNet )
	{
		float x = X - PortR;
		float y = Y - PortR;
		
		//绘制端口
		Brush s = null;
		if( FuncType == PortClientType.MASTER ) {
			s = Brushes.Red;
		}
		else if ( FuncType == PortClientType.CLIENT ) {
			s = Brushes.Blue;
		}
		else {
			MessageBox.Show( "<Module Draw> 未知的端口类型: " + FuncType );
		}
		g.FillEllipse( s, x, y, Port2R, Port2R );
		
		//绘制端口导线连接方向
		switch( DirType ) {
			case E_DirType.UP:		g.DrawLine( DirBackPen, X, Y, X, Y - 20 ); g.DrawLine( DirForePen, X, Y, X, Y - 20 ); break;
			case E_DirType.DOWN:	g.DrawLine( DirBackPen, X, Y, X, Y + 20 ); g.DrawLine( DirForePen, X, Y, X, Y + 20 ); break;
			case E_DirType.LEFT:	g.DrawLine( DirBackPen, X, Y, X - 20, Y ); g.DrawLine( DirForePen, X, Y, X - 20, Y ); break;
			case E_DirType.RIGHT:	g.DrawLine( DirBackPen, X, Y, X + 20, Y ); g.DrawLine( DirForePen, X, Y, X + 20, Y ); break;
			default:				break;
		}
		
		if( UserPortList.SelectedPort == this ) {
			g.DrawRectangle( Pens.Yellow, x - 1, y - 1, Port2R + 2, Port2R + 2 );
		}
		
		if( isWireNet ) {
			int L = 15;
			g.DrawLine( Pens.Red, x + PortR, y + PortR, x + PortR, y + PortR + L );
			g.DrawLine( Pens.Red, x + PortR, y + PortR, x + PortR, y + PortR - L );
			g.DrawLine( Pens.Red, x + PortR, y + PortR, x + PortR + L, y + PortR );
			g.DrawLine( Pens.Red, x + PortR, y + PortR, x + PortR - L, y + PortR );
		}
		
		//绘制高亮端口外形
		if( isMouseIn ) {
			Pen HighLightPortPen = null;
			if( FuncType == PortClientType.CLIENT ) {
				HighLightPortPen = rHighLightPortPen;
			}
			else {
				HighLightPortPen = bHighLightPortPen;
			}
			g.DrawEllipse( HighLightPortPen, x, y, Port2R, Port2R );
			
			//显示文本信息
			string mes = Index + " " + Name + "<" + FuncType + "-" + FuncName + "> (" + Style + ")[" + SubPortConfig + "]" + ExtValue;
			SizeF size = g.MeasureString( mes, f );
			g.FillRectangle( Brushes.White, x-size.Width/2, y - size.Height-10, size.Width, size.Height );
			g.DrawRectangle( Pens.Red, x-size.Width/2, y - size.Height-10, size.Width, size.Height );
			g.DrawString( mes, f, Brushes.Black, x-size.Width/2, y - size.Height-9 );
		}
	}
	
	//鼠标按下事件
	public bool UserMouseDown( MouseEventArgs e, int mX, int mY )
	{
		if( !isMouseInPort( mX, mY ) ) {
			return false;
		}
		isMousePress = true;
		
		return true;
	}
	
	//鼠标松开事件
	public void UserMouseUp( MouseEventArgs e, int mX, int mY )
	{
		isMousePress = false;
	}
	
	//鼠标移动事件
	public void UserMouseMove( MouseEventArgs e, int mX, int mY )
	{
		if( isNew ) {
			isNew = false;
			isMousePress = true;
			X = ox + GetPerNumber( mX );
			Y = oy + GetPerNumber( mY );
			return;
		}
		isMouseIn = isMouseInPort( mX, mY );
		
		if( isMousePress ) {
			//X = ox + GetPerNumber( mX + Per / 2 );
			//Y = oy + GetPerNumber( mY + Per / 2 );
			
			X = ox + GetPerNumber( mX - (int)ox + Per / 2 );
			Y = oy + GetPerNumber( mY - (int)oy + Per / 2 );
		}
	}
	
	//判断鼠标是否在端口上
	bool isMouseInPort( int mX, int mY )
	{
		if( mX >= X - PortR && mX <= X + PortR &&
			mY >= Y - PortR && mY <= Y + PortR ) {
			return true;
		}
		else {
			return false;
		}
	}
	
	//获取一个数字的整定, 以 Per 为单位
	public int GetPerNumber( int n )
	{
		return n / Per * Per;
	}
}
public enum E_DirType
{
	UP, DOWN, LEFT, RIGHT, NONE
}
}


